package service

import (
	"dbserver/config"
	"net"
	"net/tcpserver"
	"strings"
	"util/log"
)

var (
	ts         *telnet
	tquit      chan bool
	telnetpass string
	telnetport int
	allowip    []string
)

type telnet struct {
	sock *tcpserver.TcpServer
}

func (c *telnet) OnCreate(s *tcpserver.TcpServer) {
	c.sock = s
	c.sock.Start(1)
}

func (c telnet) OnConnect(index int, serial int, addr net.Addr) {
	bfind := false
	for _, ip := range allowip {
		host, _, _ := net.SplitHostPort(addr.String())
		if host == ip {
			bfind = true
			break
		}
	}

	if !bfind {
		c.sock.CloseConn(index, serial)
		log.TraceInfo("telnet", "client ip not allow,", addr.String())
	} else {
		log.TraceInfo("telnet", "new client connected,", addr.String())
	}

}

func (c telnet) OnDisconnect(index int, serial int) {
	log.TraceInfo("telnet", "client disconnected")

}

func (c telnet) Recv(index int, serial int, data []byte, size int) {
	c.ParseCmd(index, serial, string(data[:size]))
}

func help() []byte {
	ret := []byte(`commands:
status:		show database status, example:status uptime
`)
	return ret
}

func (c telnet) ParseCmd(index int, serial int, s string) {
	cmd := strings.Split(s, " ")

	switch cmd[0] {
	case "connect":
		err := []byte("password err")
		if len(cmd) < 2 {
			c.sock.Send(index, serial, err, len(err))
			c.sock.CloseConn(index, serial)
			return
		} else {
			if cmd[1] != telnetpass {
				c.sock.Send(index, serial, err, len(err))
				c.sock.CloseConn(index, serial)
				return
			}
		}

		welcome := []byte("welcome")
		c.sock.Send(index, serial, welcome, len(welcome))
	case "help":
		echo := help()
		c.sock.Send(index, serial, echo, len(echo))
	case "status":
		if len(cmd) >= 2 {
			ret := []byte(Status(cmd[1]))
			c.sock.Send(index, serial, ret, len(ret))
			return
		}
		fallthrough
	default:
		err := []byte("cmd or args error")
		c.sock.Send(index, serial, err, len(err))
	}
}

func StartTelnet(cfg *config.Config, ch chan bool) {
	//整个进程退出
	telnetpass = cfg.TPass
	telnetport = int(cfg.TPort)
	allowip = cfg.AllowIps

	//telnet退出
	tquit = make(chan bool)
	ts = &telnet{}
	log.TraceInfo("telnet", "start service at ", telnetport)
	tcpserver.CreateTcpServer(ts, "", telnetport, 1)
	for {
		select {
		case <-tquit:
			if ts.sock != nil {
				ts.sock.Close(true)
				ts.sock = nil
			}
			ts = nil
			log.TraceInfo("telnet", "stoped")
			return
		}
	}
}

func StopTelnet() {
	tquit <- true
}
